package api

import (
	// "fmt"
	// "io"
	"net/http"
	"net/http/httputil"
	// "strings"
	"time"

	"gitee.com/kobeyyf/apibox/handler"
)

func (api *Api) AddHandles(handles map[string]handler.HandlerFunc) {
	if api.handles == nil {
		api.handles = handles
		return
	}

	for action, handle := range handles {
		api.handles[action] = handle
	}
	return
}

func (api *Api) RouterHandler(w http.ResponseWriter, r *http.Request) {
	select {
	case api.handlerPool <- struct{}{}:
		api.logger.Infoln(r.Method, r.Host, r.RequestURI)
		if r.Method == http.MethodPost {
			if r.Header.Get("Content-Type") == "" {
				r.Header.Add("Content-Type", "application/x-www-form-urlencoded")
			}
			r.ParseForm()
		}
		// if api.apiMode == API_MODE_DEBUG {
		// 	api.logger.Infoln("get header: ", r.Header)
		// 	if r.Method == http.MethodPost {
		// 		api.logger.Infoln("params in urlencoded ", r.Form)
		// 		if len(r.Form) == 0 || strings.HasPrefix(r.Header.Get("Content-Type"), "multipart/form-data") {
		// 			r.ParseMultipartForm(6 << 20)
		// 			api.logger.Infoln("params in form-data", r.MultipartForm)
		// 		}
		// 	}
		// }
	case <-time.After(time.Microsecond):
		api.logger.Warnln("pool full, reject", r.Method, r.Host, r.RequestURI)
		w.Header().Add("Retry-After", "120")
		w.WriteHeader(503)
		w.Write([]byte("Service Unavailable"))
		return
	}
	defer func() {
		<-api.handlerPool
	}()

	appCode := r.FormValue(handler.APPCODE)

	// proxy by appcode
	proxyURL, has := api.proxyMap[appCode]
	if has {
		proxy := httputil.NewSingleHostReverseProxy(proxyURL)
		proxy.ServeHTTP(w, r)
		return
	}

	c := &handler.Context{ResponseWriter: w, Request: r, Config: api.Config}
	// run global middler

	values := c.Request.Form
	api.logger.Errorln(values)

	if mErr := runMiddleware(api.globalBefore, c); mErr != nil {
		mErr.Action = c.Request.FormValue(handler.ACTION_NAME)
		c.WriteResponse(mErr)
		return
	}

	// router by appcode
	handleApi, has := api.handleApi[appCode]
	if !has {
		c.WriteResponse(handler.NewErrorResponseWith400(handler.ErrorCode_InvalidAppCode, "AppCode Not exist: "+appCode))
		return
	}

	resp := handleApi.RouterByAction(c)
	c.WriteResponse(resp)
	return
	// runMiddleware(api.globalAfter, c)
}

func (api *Api) RouterByAction(c *handler.Context) *handler.Response {
	action := c.Request.FormValue(handler.ACTION_NAME)
	handleFunc, has := api.handles[action]
	if !has {

		resp := handler.NewErrorResponseWith400(handler.ErrorCode_InvalidAction, "Action Not Exist")
		resp.Action = action
		return resp
	}

	if mErr := runMiddleware(api.before, c); mErr != nil {
		return mErr
	}

	resp := handleFunc(c)
	if resp == nil {
		return resp
	}

	resp.Action = action
	return resp
	// runMiddleware(api.after, c)
}
